从0到1:哔哩哔哩智能客服系统的设计与实现
本期作者
小雄
哔哩哔哩客服业务技术负责人
乐文
哔哩哔哩资深开发工程师
镇宇
哔哩哔哩高级开发工程师
四百块
哔哩哔哩高级开发工程师
JasonQian
哔哩哔哩高级开发工程师
宇琪
哔哩哔哩资深开发工程师
1 背景
1.1 为什么要做新系统
B站过去的客服系统是通过外部采购获得的,已经使用了几年。然而,这个外购的系统存在一系列问题:
稳定性低,缺乏良好的拓展性和伸缩性,经常出现bug,难以应对突发的流量高峰。
与B站产品体系无法打通,难以根据业务需求进行定制化。
由于系统逻辑老旧,稳定性不佳,导致效率低下,已经不再能满足进一步提升客服效率的要求。
虽然曾考虑过采购新的客服系统,但也面临一些问题,如:
昂贵的价格,特别是在当前降本增效的大背景下,这是一个重要因素。
更重要的是,该系统仍然无法与内部系统进行良好的整合,无法支持业务定制化。
因此,B站决定开展新客服系统的自研工作。
1.2 怎么做新系统
在面对如何打造一个全新的客服系统的挑战时,我们首先开始了调研、访谈和体验。
业内调研
我们访问了一些在客服系统领域表现优秀的知名公司,从业务和技术的角度进行了深入调研。总结下来,目前客服系统比较重视以下三个关键指标,我们分别来解读一下。
智能问答拦截率(也对应人工处理率):对于一个客服系统来说,良好的智能问答功能至关重要:
提供7*24小时在线服务,无需排队等候,确保用户在任何时间都能够得到及时响应
对于用户频繁问到的问题,可以快速回答,提高效率,降低成本,从而实现更好的客户体验和更高效的资源利用。
能够快速解答大部分简单问题,同时让复杂问题有机会被人工高效解决,从而提升整体解决问题的效率和效果。
用户满意度
平均处理时长:主要指客服人员处理一次会话所需的平均时长
这些核心的指标为后续的研发指明了方向。
内部访谈和体验
我们对负责客服流程运营的团队以及各项功能团队(质检、舆情、机器人、工单、二线、数据等)和一线客服同学进行了访谈,同时也全面体验了现有的系统。特别是从各个团队的访谈中,我们获得了许多细节性的宝贵经验和一系列建议,这对我们如何具体做好产品和之后推动系统的落地起到了巨大的作用。这些经验和建议将在工作台一节中详细展示,在这里就不再展开。
1.3 新系统落地效果如何
在核心指标上,新客服系统都取得了显著的提升:
智能问答拦截率:与原有系统相比,新系统的智能问答拦截率有了巨大的提升,达到了业内先进水平。
用户满意度:也有显著的提升,表明用户对新系统的满意度较高。
平均处理时长:尽管新系统需要适应的过程,但平均处理时长仍有减少,这一点非常不易。
(保密考虑,不暴露具体数字)
此外,新客服系统的落地还提高了客服工作效率,实现了与内部业务系统的无缝对接,优化了客服功能工具,验证了自主研发的能力。
接下来,我们将从技术角度,整体和分细节方面对新客服系统进行介绍。
2 客服系统整体架构和核心业务流程
客服系统主要功能:
C端入口:进入客服的入口
智能问答:通过机器人与用户进行会话,解决用户的问题
客服坐席调度:给用户选择合适的客服人员同时兼顾客服人员的工作平衡
客服工作台:为客服人员提供便捷的工作界面和工具
知识库:汇集各类常见问题和解决方案,供客服使用
IM聊天基础能力:负责构建用户和客服之间的聊天,进行对话操作(发送文字,图片,视频)等
客服工单:用于跟踪和解决用户提出的问题和需求
权限管理:确保客服系统数据和功能的安全性
还有一些其他的功能如:质检系统,舆情系统,客服工时系统,监控系统等等。
2.1 总体功能架构
在上述描述中,我们可以认识到客服系统具有一定的复杂性。为了帮助大家从宏观上理解客服系统,以下列出了整体功能的架构图。
2.2 核心流程
同时,为了帮助大家进一步了解,这里列出了客服系统的核心流程。
3 核心功能设计和实现
我们将按照用户一次完整的访问客服系统所需的先后次序,介绍各个核心功能的设计与实现。用户从用户入口进入,依次会经历智能问答、客服坐席调度以及与客服聊天(工作台)等核心功能。最后,我们将讲解整个系统的基础支撑——权限管理的设计与实现。
3.1 用户入口
首先简单看一下哔哩哔哩客服的用户入口。
当用户进入聊天框,首先会进入智能问答环节,如果智能问答无法帮助用户解决问题,用户可以选择进一步联系人工客服来解决问题。
3.2 智能问答
在客服的业务场景中,智能问答是一个非常重要的需求,它具备了人工不可比拟的优势:
提供7*24小时的在线服务
高峰时期无需排队等候
用户频繁问到的问题,可以快速回答
大部分简单问题得以快速自助解决
从而从整体上提高效率,降低成本,实现更好的客户体验和更高效的资源利用。
下面,我们将简要介绍哔哩哔哩客服系统的智能问答。
3.2.1 智能问答系统概览
目前,哔哩哔哩客服系统在执行智能问答任务时,会根据匹配度的不同提供两种回答方式:当匹配度较高时,系统会直接给出答案;而当匹配度只是中等时,系统则会提供一个“您想咨询的问题可能是”的列表。这个策略的目的是为了提供更准确、更有用的回答,以帮助用户更快地找到他们需要的信息。
机器人问答-直接给出答案 | 机器人问答-“您想咨询的问题可能是” |
3.2.2 机器人问答技术调研
机器人问答技术在实现上主要分为两种类型:检索式和生成式。
检索式:检索式模型通常利用神经网络技术,将大量的预训练语料数据输入到模型中进行训练。在完成训练后,模型能够对新的输入进行分类、匹配和回答问题。这种方案的实现主要依赖于大规模的预训练数据和高效的检索算法。
生成式:另一种类型的是生成式模型,它主要采用深度学习技术以及最新的大语言模型,通过学习大量数据来生成文本。这种方案通常使用循环神经网络(RNN)或变换器(Transformer)等结构,能够处理序列数据并生成新的序列。与检索式模型不同,生成式模型在训练过程中会直接生成目标文本,而不是通过检索匹配。
总的来说,检索式和生成式两种模型各有特点,各有优势,在机器人问答系统中都有应用。具体选择哪种模型,往往需要根据具体的应用场景和需求来决定。
方案对比:
方案 | 场景 | 数据需求 | 准确性 | 性能 | 复杂性 |
检索式 | 主要适用于对知识库的检索和筛选,比如问答系统、知识库管理、智能客服等 | 依赖,需要丰富的结构化语料库 | 本质上是从已有数据集中检索最匹配的数据,准确性高 | 毫秒级 | 低 |
生成式 | 主要适用于需要生成自主文本或任务的应用场景,如对话生成、文本创作、任务调度等 | 依赖,无需结构化 | 生成的质量可能会受到模型的训练数据和质量的限制,可能会出现不准确、无意义或不一致的输出 | 秒级 | 高 |
在电商客服场景下,回答用户问题的准确性至关重要,宁可选择不回答也不能够回答错误。相比之下,生成式答案会受到多种因素的影响,导致结果不可控。而检索式答案来源于知识库,可以提供更加准确的问题解答。虽然检索式在处理一些长尾问题或者冷门领域的问题时表现不佳,但是可以通过人工干预来丰富知识库进行优化。综合考虑到这些因素,最终选择了检索式实现。
3.2.3 向量搜索和基于Faiss实现的智能问答
向量搜索基本原理
给定一个向量集合:
和一个待查询的向量:
从 个向量里面找到距离 某种距离(比如 L2 距离)最近的 个向量。
其应用包括
从语料库里面找到距离某个语句最相近的一句话。
从图片库里面找到距离某张图片最类似的一张图片。
还能查找别的,比如视频、音频、动图、基因序列、搜索条目等。
这些东西(图片、词语、句子、视频等)都可以用向量表示出来,如下图:
这个事情看起来很简单,但是当我们的数据库变得特别大时,这件事情就变得比较困难了。因此这里就专门来研究如何做这样的向量搜索。
Faiss简介
Faiss(Facebook AI Similarity Search) 是 Facebook AI 开发的用于高效相似性搜索和向量聚类的库。
Faiss 总体使用过程可以分为三步:
构建训练数据(以矩阵形式表达);
挑选合适的 Index (Faiss 的核心部件),将训练数据 add 进 Index 中;
Search,也就是搜索,得到最后结果。
详细解释,即为:首先根据原始向量构建一个索引文件,再根据索引文件进行查询。初次查询前需要进行train和add过程,后续若要进行索引的添加可以再次使用add添加索引,如下图所示:
基于Faiss实现的智能问答
在实现检索式的过程中,主要任务是找到与用户提问语句最相似的问法,从而获取对应的答案。这个过程包括以下步骤:
数据准备:建立知识库,包含标准问、相似问以及对应的答案。每个标准问有多个相似问,并对应唯一的答案。
文本向量化:使用BERT模型将问题和相似问转化为向量表示。BERT模型采用预训练方式,能够将输入的文本转化为对应的向量表示。公司已有基于社区数据训练的bert-embedding服务,体验效果满足需求,因此使用该服务进行文本向量化。
相似度计算:使用Faiss库进行相似度计算。Faiss库是一种针对聚类和相似性搜索的工具,为稠密向量提供高效相似度搜索和聚类,支持十亿级别向量的搜索,是目前最为成熟的近似近邻搜索库。
搜索匹配:将用户问题向量传入Faiss库中,使用相似度计算方法对问题进行匹配,找到最相似的TopN问题向量(或者说相似问)。
答案选取:根据相似度结果高低,直接给出问题对应的答案或者“您想咨询的问题可能是”列表。如果相似度很低,则会转接人工。
基于Faiss的智能问答如下图所示
Faiss索引选择实践
Faiss提供的索引很多,需要根据数据集的大小和机器的性能来选取合适的索引。
基于准确查找
仅有IndexFlatL2索引可以提供确切的结果,但是性能上会比较差,仅适用数据量比较少的情况,通常为其他索引准确度提供基准。
基于内存限制
基于数据集限制
由于我们数据集在10M以内,最终选取了"IVF{IVFK}_HNSW32,Flat",如果小于10M,IVFK根据依据4*sqrt(N)~16*sqrt(N)动态算,如果大于10M,则IVFK为65536。部分代码如下:
if len(x) < 1000000:
ivfK = findIVFK(len(x))
else:
ivfK = 65536
factory_str = f'IVF{ivfK}_HNSW32,Flat'
def findIVFK(N: int):
sqrtN = math.sqrt(N)
print(sqrtN, 4 * sqrtN, 16 * sqrtN)
i = 2
while True:
i *= 2
if 4 * sqrtN <= i <= 16 * sqrtN and N // 256 <= i <= N // 30:
return i
if i > 4096:
return 512
3.3 客服坐席调度
3.3.1 什么是客服坐席调度
客服坐席调度主要涉及为用户提供选择人工客服的一系列调度策略和逻辑。通过这些策略和逻辑,用户可以快速地联系到合适的人工客服来处理他们的问题,从而获得更及时和有效的帮助。调度策略可以包括根据用户的信息、问题类型、服务需求等因素来分配客服坐席,以及根据坐席的服务质量和服务水平来进行评估和调整。通过合理的调度策略和逻辑,可以提高用户满意度和解决效率,从而提升整个客户服务的品质和用户体验。
大致可以通过以下流程图说明:
坐席调度策略在客户服务中扮演着关键角色。以下是可以看到的几种常见策略及其优势:
均衡分配策略:这种策略将用户请求平均分配给各个坐席,从而平衡工作负荷,提高整体服务效率。它的优点在于保证了所有坐席的工作量公平分配,防止了某些坐席过度劳累,也防止了某些坐席空闲的情况。
熟客优先策略:根据用户的历史服务记录和需求,将用户优先分配给曾经提供过优质服务的坐席。这种策略的优点在于提高了用户的服务体验,因为熟客通常能够得到更快速、更准确的服务。
上次服务优先策略:将用户分配给上一次为其提供服务的坐席,以提高用户满意度和连续服务效率。这种策略的优点在于可以维持用户对特定坐席的信任,有利于提供持续、一致的服务。
指定分配策略:根据特定条件或需求,将用户请求分配给指定的坐席。这种策略的优点在于可以满足某些特殊需求,或者处理复杂问题。
在进行了深入研究后,我们发现均衡分配策略是业内使用最广泛和最常用的策略,也被广泛应用于各种客户服务系统。这是因为均衡分配策略可以确保所有坐席的工作量公平分配,防止过度劳累,防止坐席空闲,从而提高整体服务效率。同时,我们也发现,熟客优先策略、上次服务优先策略和指定分配策略都有其特定的适用场景,可以在需要的时候作为均衡分配策略的补充。因此,我们的选择是采用均衡分配策略作为基础的坐席调度策略,同时根据特定情况灵活运用其他策略。
3.3.2 均衡分配
在介绍均衡分配前,有几个名词需要提前解释一下:
饱和度:客服可以服务的最大用户数,在客服被邀请进入系统时会被设置
均衡分配:本系统会在不超过饱和度的情况下,客服均衡获取用户分配
3.3.3 如何实现均衡分配
以下是我们客服系统中均衡分配的实现逻辑:
注意,分配是以技能组为单位进行分配。假设一个技能组有两个客服,A客服的饱和度为5,B客服的饱和度为10。
如果A客服当前服务的用户数少于B客服当前服务的用户数,并且都低于各自的饱和度,那么如果有用户进线,系统会优先分配给A客服。
如果A客服和B客服当前服务的用户数相等,并且都低于各自的饱和度,那么如果有用户进线,系统会随机均衡分配给A或B客服。
如果A客服已经达到了自己的饱和度,那么如果有用户进线,A客服将不会被分配到该用户进线,该用户将被分配给还没有达到饱和度的客服,并根据上述1和2的原则进行分配。
如果A客服和B客服都已经达到了各自的饱和度,那么系统将进入排队状态。
3.3.4 排队
这里可以用Redis的Zset数据结构,可以方便的根据用户排队时间进行先后次序排队:
ZADD:用于添加元素,Key使用技能组id,每个技能组id关联一个有序集,有序集Member是用户id,Score是用户进入排队的时间戳,这里可以用于添加排队的用户。
ZRANK:返回有序集中成员的排名,可用于展示当前排名
ZREM:移除有序集中的一个或多个成员,可用于退出排队
ZRANGE:返回有序集中指定区间内的成员,可用于客服工作台会话邀请场景
ZPOPMIN:返回最低得分的成员,也就是最早排队的成员,可以用于自动进线场景
ZCOUNT:返回计算有序集合中指定分数区间的成员数量,可用于计算排队长度
ZSCORE:返回有序集中,成员的分数值,可用于查看用户排队时间
以上命令基本可以满足排队场景各项操作。
3.3.4 自动进线和会话邀请
当用户进入排队后,有两种方式可以获得人工服务:自动进线和会话邀请。
自动进线:系统会持续扫描未达到饱和度的客服,如果发现有客服尚未达到饱和度,会自动将队列中的用户分配给该客服。
会话邀请:客服人员可以根据自身能力,即使已经超过饱和度,仍然可以邀请排队中的用户进入会话。可以一次性邀请一个或多个用户进入会话。
3.4 客服工作台
3.4.1 工作台常见功能
工作台是客服人员与用户会话的主战场,其功能非常多,大致有以下一些:
功能块 | 功能点 | 备注 |
对话管理 | 客服信息 | 客服工号及内部昵称 |
坐席状态 |
| |
当前会话列表 | 当前所有进行中的会话在此呈现,按进线顺序固定排列;若会话完结,则移至历史会话 | |
历史会话列表 | ||
邀请会话 | 用户可邀请排队中的用户进入会话 | |
关闭 | 用户会话关闭后,饱和度-1,移入历史会话 | |
对话操作 | 发送常规消息 | |
转接 | 当前客服处理不了,可以转接给其他客服 | |
新建工单 | 客服当前无法解决的问题可以通过工单来流转解决 | |
查看历史会话 | ||
邀请评价 | 邀请用户评价 | |
客服总结 | ||
辅助工具 | 客户信息 | |
智能话术 | 根据用户的 | |
知识库搜索 | 可以搜索个人库和公共库 | |
业务自定义Tab | 各个业务方可以将自己的自定Tab嵌入客服系统工作台 |
3.4.2 部分亮点和智能化功能示意
功能 | 新客服系统 |
智能话术 | |
辅助工具 (可以嵌入业务方页面) | |
客服总结优化 -通过数字来选择 | |
会话列表丰富的标签和过滤条件 | |
自动欢迎语 |
(限于篇幅,这里也不列举过多)
3.4.3 工作台技术难点
多位用户同时聊天,快速切换,卡顿问题的解决
为了确保客服在快速切换时能够第一时间看到消息,可以采用以下方式在会话切换时进行缓存更新渲染:
1. 定时更新缓存:WebWorker在后台定时获取并更新当前会话信息到缓存中;
2. 缓存预渲染:在客服切换会话时,直接渲染本地内存中缓存的内容,确保第一时间看到消息;
3. 同步机制:在客服切换会话时,立刻发出接口请求,将最新的会话信息实时更新到缓存中,以确保缓存与实际会话信息的一致性。
通过以上方式,可以确保客服在快速切换会话时能够第一时间看到消息,提高服务效率。
DOM会随消息数量线性增长,从而导致浏览器卡顿甚至崩溃,如果每次都动态拉取数据,会对服务端造成压力,通过维护缓存数据+虚拟列表+虚拟滚动的方式来渲染消息信息,保证系统可以在浏览器中长时间运行流畅。
工作台消息种类繁多难题解决
工作台消息种类较多,且消息本身会与业务产生关联,如果不合理抽离组件,会影响业务的扩展;
如上图所示,多个消息类型对应多个功能卡片,每个功能卡片会组装多个基础组件,如文本消息 = 纯文本框 + 信息面板,以此确保了业务快速扩展能力和基础组件的复用能力。
3.5 权限管理
RBAC模型
迄今为止,最普及的权限设计模型是RBAC模型,即基于角色的访问控制(Role-Based Access Control)。因此,本次客服系统也参考了RBAC模型。
RBAC就是用户通过角色与权限进行关联。
简单地说,一个用户拥有若干角色,每一个角色拥有若干权限。
这样,就构造成“用户-角色-权限”的授权模型。
在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系。
这种授权模型提供了了一种灵活的授权方式,可以方便地实现用户之间的授权和访问控制,同时也简化了权限管理流程,提高了管理效率。
RBAC模型示意图如下:
目前客服只要求一个用户可以有多个角色,一个角色只有一个权限,如下所示:
RBAC模型目前完全可以支撑当前的客服的权限管理。
权限管理界面
在管理员页面上,可以方便的进行技能组(角色)分配,如下所示:
4 规划和展望
4.1 大语言模型尝试和探索
当前备受关注的大语言模型我们也进行了探索。我们与公司AI部门合作,将客服与用户的真实聊天记录以及知识库作为训练数据,给大模型进行训练,并且进行了测试。
总体上,我们学到了客服的回答风格,使回答更为流畅自然,与检索式问答相比,这种方式更容易让客户在心理上接受,并能够做出一些决策。
情绪抚慰
意图识别
自我决策
当然,我们也遇到了强制回答和回答无法解决问题的情况。要解决问题,需要根据客户的具体问题和订单状态来回答。不过,大型语言模型是未来的趋势,值得我们进一步探索。
除了智能问答领域,目前大型语言模型还可以应用于智能话术场景,或者在一些偏向咨询的场景中试用。此外,业内也有在偏向咨询的电商售前场景和互联网教育咨询场景中使用大型语言模型的案例
5 其他
工单部分后续单独有文章讲述
感谢参与客服系统开发的其他同学,公司AI部门的对接同学(麻由,天行,水溶,印等),以及产品运营,客服一线同学
6 参考文献
1.https://www.pinecone.io/learn/series/faiss/vector-indexes/
2.https://towardsdatascience.com/similarity-metrics-in-nlp-acc0777e234c
3.https://www.pinecone.io/learn/series/faiss/faiss-tutorial/
以上是今天的分享内容,如果你有什么想法或疑问,欢迎大家在留言区与我们互动,如果喜欢本期内容的话,欢迎点个“在看”吧!
往期精彩指路